home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #2 / Amiga Plus CD - 2004 - No. 02.iso / AmigaPlus / Tools / mOS_Pegasos / cimon / cimon096src.lha / imon.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-04-05  |  4.4 KB  |  196 lines

  1. /* ----------------------------------------------------------------------
  2.    cimon - a UNIX command line client for the fli4l imon daemon.            
  3.  
  4.    Public domain, 2001-2002, Rene Herman <rene.herman@mail.com>         
  5. ---------------------------------------------------------------------- */
  6.  
  7. #include <signal.h>
  8. #include <string.h>           /* FD_ZERO expands to bzero() on MacOS X */
  9.  
  10. #include <unistd.h>
  11.  
  12. #include <sys/types.h>
  13. #include <sys/socket.h>
  14. #include <sys/time.h>
  15.  
  16. #ifdef __EMX__            /* EMX fails to declare select() in unistd.h */
  17. #include <sys/select.h>
  18. #endif
  19.  
  20. #include <netinet/in.h>
  21. #include <arpa/inet.h>
  22. #include <netdb.h>
  23.  
  24. #include "cimon.h"
  25.  
  26. /*--- globals */
  27.  
  28. unsigned short port = IMON_PORT; /* TCP port number             */      
  29. const char    *password;         /* imond password              */
  30.  
  31. /*--- filescopes */
  32.  
  33. static int  sock;                /* socket                       */
  34. static int  empty = 1;           /* communications channel empty */
  35.  
  36. #define     BUFF_SIZE 4096       /* 0 < BUFF_SIZE <= SSIZE_MAX  */
  37. static char buff[BUFF_SIZE];     /* command/reply buffer        */
  38. static int  bufc = 0;            /* buffer counter              */
  39.  
  40. /*--- private functions */
  41.  
  42. static void buff_send(void)
  43. {
  44.     if (write(sock, buff, bufc) != bufc)
  45.         exit_errno("Write error");
  46.     empty = bufc = 0;
  47. }
  48.  
  49. static void buff_putc(const char c)
  50. {
  51.     if (bufc == BUFF_SIZE)
  52.         buff_send();
  53.     buff[bufc++] = c;
  54. }
  55.  
  56. static void buff_puts(const char *s)
  57. {
  58.     while (*s)
  59.         buff_putc(*s++);
  60. }
  61.  
  62. static void send_command(void)
  63. {
  64.     buff_putc('\r');
  65.     buff_putc('\n');
  66.     buff_send();
  67. }
  68.  
  69. static void send_quit(void)
  70. {
  71.     buff_puts("quit");
  72.     send_command();
  73.  
  74. #define REPLY_OK  1
  75. #define REPLY_ERR 2
  76.  
  77. static void get_reply(void)
  78. {
  79.     static char *s;
  80.     static char  c = '\n';
  81.  
  82.     fd_set         sockset;
  83.     struct timeval timeout;
  84.     int            i;
  85.     
  86.     /* 10 second timeout */
  87.     FD_ZERO(&sockset);
  88.     FD_SET(sock, &sockset);      
  89.     timeout.tv_sec = 10;
  90.     timeout.tv_usec = 0;
  91.     
  92.     if ((i = select(sock + 1, &sockset, NULL, NULL, &timeout)) < 0)
  93.         exit_errno("Internal error (select)");
  94.     else if (!i)
  95.         exit_error("Timeout waiting for reply from remote");
  96.     
  97.     if ((i = read(sock, buff, BUFF_SIZE)) < 0)
  98.         exit_errno("Read error");
  99.     else if (!i)
  100.         exit_error("Connection closed by remote");
  101.     
  102.     /* scan for (\n terminated) line starting with OK or ERR */
  103.     do {
  104.         if (c == '\n')
  105.             s = buff[bufc] == 'O' ? "K" : buff[bufc] == 'E' ? "RR" : NULL;
  106.         else if (s && *s && buff[bufc] != *s++)
  107.             s = NULL;
  108.         c = buff[bufc++];
  109.     } while (--i);
  110.  
  111.     /* "empty" doubles as OK/ERR indicator */    
  112.     empty = s && !*s && c == '\n' ?
  113.         (*(s - 1) == 'K' ? REPLY_OK : REPLY_ERR) : 0;
  114. }
  115.  
  116. static void send_command_get_reply()
  117. {
  118.     send_command();
  119.     do {
  120.         get_reply();
  121.         write(STDOUT_FILENO, buff, bufc);
  122.         bufc = 0;
  123.     } while (!empty);
  124. }
  125.  
  126. static void check_password(void)
  127. {
  128.     buff_puts("pass ");
  129.     buff_puts(password);
  130.     send_command();
  131.     do {
  132.         get_reply();
  133.         bufc = 0;
  134.     } while (!empty);
  135.     if (empty != REPLY_OK) {
  136.         send_quit();
  137.         exit_error("Password rejected by remote");
  138.     }
  139. }
  140.  
  141. static void flush()
  142. {
  143.     if (bufc || !empty)
  144.         send_command_get_reply();
  145. }
  146.  
  147. /*--- global functions */
  148.  
  149. void imon_open(const char * const hostname)
  150. {
  151.     struct sockaddr_in name;
  152.     struct hostent    *host;
  153.  
  154.     name.sin_family = AF_INET;
  155.     name.sin_port   = htons(port);
  156.     if ((name.sin_addr.s_addr = inet_addr(hostname)) == INADDR_NONE) {
  157.         if (!(host = gethostbyname(hostname)))
  158.             exit_error("Can't find `%s': %s", hostname, herrorstr(h_errno));
  159.         name.sin_addr = *(struct in_addr *)host->h_addr;
  160.     }
  161.  
  162.     if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
  163.         exit_errno("Error creating socket");
  164.     if (connect(sock, (struct sockaddr *)&name, sizeof name))
  165.         exit_errno(hostname);
  166.  
  167.     if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
  168.         exit_errno("Internal error (signal)"); 
  169.  
  170.     if (password)
  171.         check_password();
  172. }
  173.  
  174. void imon_putc(const char c)
  175. {
  176.     if (c == '\n')
  177.         flush();
  178.     else
  179.         buff_putc(c);
  180. }
  181.  
  182. void imon_puts(const char *s)
  183. {
  184.     while (*s)
  185.         imon_putc(*s++);
  186. }
  187.  
  188. void imon_quit(void)
  189. {
  190.     flush();
  191.     send_quit();
  192.     if (close(sock)) 
  193.         exit_errno("Can't close connection");
  194. }
  195.